import libtcodpy as L
from Commons import *
from Creature import *
class Tile:#tile
	def displayTile(self,g,x,y):#display the tile
		L.console_put_char_ex(g,x,y,' ',L.black,L.Color(128,128,128))
	def isBuildable(self):#can things be built on the tile
		return True
	def isSeeThrough(self):#can things see through the tile
		return False
	def getID(self):#get the type of tile
		return TILE_TILE
	def isWalkable(self):
		return True
class Wall(Tile):#wall-blocks movement
	def displayTile(self,g,x,y):
		L.console_put_char_ex(g,x,y,' ',L.white,L.black)
	def isBuildable(self):
		return False
	def getID(self):
		return TILE_WALL
	def isWalkable(self):
		return False

class Floor(Tile):#floor-allows movement
	def displayTile(self,g,x,y):
		L.console_put_char_ex(g,x,y,' ',L.black,L.white)
	def isBuildable(self):
		return False
	def getID(self):
		return TILE_FLOOR

class Door(Tile):#door-allows movement
	def displayTile(self,g,x,y):
		L.console_put_char_ex(g,x,y,197,L.black,L.yellow)
	def isBuildable(self):
		return False
	def getID(self):
		return TILE_DOOR

class UpStair(Tile):#upstairs-allows movement SPECIAL
	def displayTile(self,g,x,y):
		L.console_put_char_ex(g,x,y,'<',L.black,L.white)
	def isBuildable(self):
		return False
	def getID(self):
		return TILE_UP_STAIR

class DownStair(Tile):#downstairs-allows movement SPECIAL
	def displayTile(self,g,x,y):
		L.console_put_char_ex(g,x,y,'>',L.black,L.white)
	def isBuildable(self):
		return False
	def getID(self):
		return TILE_DOWN_STAIR

class UpDownStair(Tile):#updownstairs-allows movement SPECIAL
	def displayTile(self,g,x,y):
		L.console_put_char_ex(g,x,y,'X',L.black,L.white)
	def isBuildable(self):
		return False
	def getID(self):
		return TILE_UP_DOWN_STAIR



class Space(Tile):
	#def displayTile(self,g,x,y):
	#	L.console_put_char_ex(g,x,y,' ',L.blue,L.black)
	def getID(self):
		return TILE_SPACE

class Room:
	pass

#checks the map dimensions for sanity
class dimensionCheck:
	def __init__(self):
		self.value = 0
		self.max = 0
		self.set = False
	def incrementValue(self):#increment the value for a map dimension
		self.value += 1
		if (self.max < self.value):#set the limit if it goes past the map dimension and the limit hasn't been set, otherwise, trigger an error
			if (not self.set):
				self.max = self.value
			else:
				StopConsoleErrorScreen("Error: could not load savefile due to inconsistent map dimensions!\nThe map may have been corrupted.")
	def resetValue(self):#set the limit
		if (self.value <= 0):
			return
		self.value = 0
		self.set = True

class TileLayer(MapLayer):#the layer used for tiles
	def __init__(self,xlength,ylength):
		MapLayer.__init__(self,xlength,ylength,Space())

#reversed dictionary, you get a tile from a designation -- used for savefiles
mapdict = {TILE_TILE:Tile(),TILE_WALL:Wall(),TILE_FLOOR:Floor(),TILE_DOOR:Door(),TILE_SPACE:Space(),TILE_UP_STAIR:UpStair(),TILE_DOWN_STAIR:DownStair(),TILE_UP_DOWN_STAIR:UpDownStair()}

class Map:#A 2d map, no 3d for dwarf mode, have to find creative uses for it.
	layers = dict()
	def __init__(self,xlength=1,ylength=1):
		self.xlength = xlength
		self.ylength = ylength
		self.viewer = None
		self.layers[L_TILES] = TileLayer(self.xlength,self.ylength)#add a tile layer
		self.layers[L_CREATURES] = CreatureLayer(self.xlength,self.ylength)#add a creature layer
	def changeViewer(self,viewer):#change the MapViewer that views the map
		self.viewer = viewer
	def resizeMap(self,newxlength,newylength):#resize the map
		self.xlength = newxlength
		self.ylength = newylength
		self.layers[L_TILES].resizeLayer(self.xlength,self.ylength)
		self.layers[L_CREATURES].resizeLayer(self.xlength,self.ylength)
	def withinBounds(self,xpoint,ypoint):#is the point within bounds of the map?
		if (xpoint < 0 or xpoint >= self.xlength or ypoint < 0 or ypoint >= self.ylength):
			return False
		return True
	def __getitem__(self,key):#get a layer from the map
		return self.layers[key]
	def __setitem__(self,key,value):#change something inside the map
		self.layers[key] = value
	def save(self):#save the map
		savestring = ""
		for y in range(self.ylength):
			for x in range(self.xlength):
				savestring+=self[L_TILES][x][y].getID()
			savestring+="\n"
		savestring+="\\ENDMAP\n"
		savestring+=self[L_CREATURES].save()
		savestring+="\\ENDCREATURES\n"
		return savestring
	def load(self,data):#load the map XXX:Seperate it into seperate sections?
		cursor = 0
		array = [[]]
		y=0
		x=dimensionCheck()
		#load the tiles
		while (data[cursor:cursor+8] != "\\ENDMAP\n"):#ends the transcription of the tilelayer
			x.resetValue()
			while (data[cursor:cursor+1] != '\n'):
				try:
					array[x.value].append(mapdict[data[cursor]])
				except IndexError:#crude code to make the indexes work
					while (len(array) <= x.value):
						array.append([])
					array[x.value].append(mapdict[data[cursor]])
				x.incrementValue()
				cursor+=1
			y+=1
			cursor+=1
		cursor+= 8
		self.resizeMap(x.value,y)
		self[L_TILES].tiles = array
		self[L_CREATURES].__init__(x.value,y)#do creatures
		cursorend = cursor
		while (data[cursorend:cursorend+14] != "\\ENDCREATURES\n"):
			cursorend+= 1
		creaturedata = data[cursor:cursorend-1]
		self[L_CREATURES].load(creaturedata)

class MapViewer:#the df style map viewer, always attached to the map
	def __init__(self,themap):
		self.miny = 0
		self.maxy = themap.ylength
		self.minx = 0
		self.maxx = themap.xlength
		#scrolling
		self.scrollx = 0
		self.scrolly = 0
		self.width = SCREEN_WIDTH
		self.height = SCREEN_HEIGHT
		self.graphics = L.console_new(SCREEN_WIDTH,SCREEN_HEIGHT)#consoles
		self.creaturegraphics = L.console_new(SCREEN_WIDTH,SCREEN_HEIGHT)
		self.selectiongraphics = L.console_new(SCREEN_WIDTH,SCREEN_HEIGHT)
		self.completedroomselections = []#the selections for rooms that have been completed
		L.console_set_key_color(self.selectiongraphics,L.black)#make the selection console transparent except for the colored lines
		self.map = themap
	def scrollX(self,val):#scroll x from overview
		if (self.scrollx+val+self.width-1 > self.maxx):
			val = self.maxx-self.width-self.scrollx+1
		elif (self.scrollx+val+1 < self.minx):
			val = self.minx-self.scrollx-1
		self.scrollx += val
	def scrollY(self,val):#scroll y from overview
		if (self.scrolly+val+self.height-1 > self.maxy):
			val = self.maxy-self.height-self.scrolly+1
		elif (self.scrolly+val+1 < self.miny):
			val = self.miny-self.scrolly-1
		self.scrolly += val
	def blitView(self):#blit everything
		L.console_blit(self.graphics,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,0,1.0,1.0)
		L.console_blit(self.creaturegraphics,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,0,1.0,0.0)
		L.console_blit(self.selectiongraphics,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,0,0.0,0.5)
	def displayAll(self):#update everything
		self.displayCreatures()
		self.displayView()
		self.displaySelections()
	def displayView(self):#display the tiles
		L.console_clear(self.graphics)
		for y in range(self.height):
			ysc = y+self.scrolly#y scroll
			if (ysc >= self.miny and ysc < self.maxy):#if in the map
				for x in range(self.width):#x scroll
					xsc = x+self.scrollx
					if (xsc >= self.minx and xsc < self.maxx):#if in the map
						self.map[L_TILES][xsc][ysc].displayTile(self.graphics,x,y)#display it
		self.blitView()#blit it
		
	def displayCreatures(self):#display the creatures
		L.console_clear(self.creaturegraphics)
		for creature in self.map[L_CREATURES]:
			if (creature.x >= self.scrollx and creature.x < self.width+self.scrollx and creature.y >= self.scrolly and creature.y < (self.height+self.scrolly)):
				#put the creature here		
				L.console_put_char_ex(self.creaturegraphics,creature.x-self.scrollx,creature.y-self.scrolly,creature.ascii, creature.color,L.black)
				if (creature.faction == PLAYER_FACTION):#show friendlies in green
					L.console_set_fore(self.creaturegraphics,creature.x-self.scrollx,creature.y-self.scrolly,L.green)
	def displaySelections(self):#display the selections
		L.console_clear(self.selectiongraphics)
		for selection in self.completedroomselections:#for room selections
			selection.displaySelection(L.Color(139,69,19), L.Color(0,0,1))#brown and black				
					
					
					
					

	def viewtomapX(self,x):
		return x+self.scrollx
	def viewtomapY(self,y):
		return y+self.scrolly
	def maptoviewX(self,x):
		return x-self.scrollx
	def maptoviewY(self,y):
		return y-self.scrolly
	def pointinview(self,x,y):
		if (y >= 0 and y < self.height and x >= 0 and x < self.width):
			return True
		return False
	def save(self):
		data = ""
		data += str(self.scrollx)+"\n"
		data += str(self.scrolly)+"\n"
		return data 
	def load(self,data):
		data = data.split("\n")
		self.scrollx = int(data[0])
		self.scrolly = int(data[1])
	def scrolltoXY(self,scrollx,scrolly):
		self.scrollx = scrollx
		self.scrolly = scrolly
